/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package elderberryni2;

import elderberryni2.data.ElderberryProperties;
import elderberryni2.data.TelemetryDataSet;
import elderberryni2.data.container.DataContainer;
import elderberryni2.datareader.DataReader;
import elderberryni2.datareader.NetworkUDPReader;
import elderberryni2.datareader.TestModeReader;
import elderberryni2.enums.NetworkType;
import elderberryni2.exceptions.NoSuchTimeableArrayListException;
import elderberryni2.interfaces.IChartSavable;
import elderberryni2.interfaces.IDataReadable;
import elderberryni2.panels.*;
import elderberryni2.utils.CSVWriter;
import elderberryni2.utils.Utils;
import java.awt.Component;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.String;
import java.util.HashMap;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.AbstractButton;
import javax.swing.JPanel;

/**
 *
 * @author warringer
 */
public class Main extends javax.swing.JFrame implements Runnable {
    /**
     * Creates new form ElderberryNi
     */
    public Main() {
        setupLogging();
        initComponents();
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jTabbedPane1 = new javax.swing.JTabbedPane();
        jPanel1 = new javax.swing.JPanel();
        jLabel4 = new javax.swing.JLabel();
        utcLabel = new javax.swing.JLabel();
        jLabel6 = new javax.swing.JLabel();
        metLabel = new javax.swing.JLabel();
        tabbedDataPanels = new javax.swing.JTabbedPane();
        jLabel5 = new javax.swing.JLabel();
        csvSaveButton = new javax.swing.JToggleButton();
        rocketNameField = new javax.swing.JTextField();
        jButton1 = new javax.swing.JButton();
        dataPointsPerSecondSpinner = new javax.swing.JPanel();
        testModeToggle = new javax.swing.JCheckBox();
        testModeRun = new javax.swing.JToggleButton();
        testModePause = new javax.swing.JToggleButton();
        jLabel1 = new javax.swing.JLabel();
        sourceTCP = new javax.swing.JRadioButton();
        sourceUDP = new javax.swing.JRadioButton();
        jLabel2 = new javax.swing.JLabel();
        ipAdress = new javax.swing.JTextField();
        jLabel3 = new javax.swing.JLabel();
        portField = new javax.swing.JTextField();
        jLabel7 = new javax.swing.JLabel();
        jLabel8 = new javax.swing.JLabel();
        jLabel9 = new javax.swing.JLabel();
        duractionDaysSpinner = new javax.swing.JSpinner();
        jLabel10 = new javax.swing.JLabel();
        duractionHoursSpinner = new javax.swing.JSpinner();
        jLabel11 = new javax.swing.JLabel();
        duractionMinSpinner = new javax.swing.JSpinner();
        jLabel12 = new javax.swing.JLabel();
        duractionSecsSpinner = new javax.swing.JSpinner();
        jLabel13 = new javax.swing.JLabel();
        savesPerSecond = new javax.swing.JSpinner();
        saveConfigButton = new javax.swing.JButton();
        mainChartPanel = new elderberryni2.panels.MainChartPanel(this);
        enviroChartPanel = new elderberryni2.panels.EnviroChartPanel(this);
        groundPathPanel = new elderberryni2.panels.GroundPathPanel(this);

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("Elderberry Ni V2.0");
        setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
        setLocationByPlatform(true);
        setResizable(false);

        jLabel4.setText("Universe Time:");

        utcLabel.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING);
        utcLabel.setText("0");

        jLabel6.setText("Mission Time:");

        metLabel.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING);
        metLabel.setText("0");

        jLabel5.setText("Mission Name:");

        csvSaveButton.setText("Save to CSV");
        csvSaveButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                csvSaveButtonActionPerformed(evt);
            }
        });

        jButton1.setText("Clear");
        jButton1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton1ActionPerformed(evt);
            }
        });

        rocketNameField.setText("Rocket");
        rocketNameField.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                rocketNameFieldActionPerformed(evt);
            }
        });
        rocketNameField.addPropertyChangeListener(new java.beans.PropertyChangeListener() {
            public void propertyChange(java.beans.PropertyChangeEvent evt) {
                rocketNameFieldPropertyChange(evt);
            }
        });

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(tabbedDataPanels)
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
                        .addComponent(jLabel5)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(rocketNameField, javax.swing.GroupLayout.DEFAULT_SIZE, 133, Short.MAX_VALUE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jLabel4)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(utcLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 116, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(18, 18, 18)
                        .addComponent(jLabel6)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(metLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 116, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(25, 25, 25))
                    .addGroup(jPanel1Layout.createSequentialGroup()
                        .addComponent(csvSaveButton)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jButton1)
                        .addGap(0, 0, Short.MAX_VALUE)))
                .addContainerGap())
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel4)
                    .addComponent(utcLabel)
                    .addComponent(jLabel6)
                    .addComponent(metLabel)
                    .addComponent(jLabel5)
                    .addComponent(rocketNameField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(tabbedDataPanels, javax.swing.GroupLayout.PREFERRED_SIZE, 473, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 21, Short.MAX_VALUE)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(csvSaveButton)
                    .addComponent(jButton1))
                .addContainerGap())
        );

        jTabbedPane1.addTab("Flight Data", jPanel1);

        testModeToggle.setText("Run in Test Mode");
        testModeToggle.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                testModeToggleActionPerformed(evt);
            }
        });

        testModeRun.setText("Start");
        testModeRun.setEnabled(false);
        testModeRun.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                testModeRunActionPerformed(evt);
            }
        });

        testModePause.setText("Pause");
        testModePause.setEnabled(false);
        testModePause.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                testModePauseActionPerformed(evt);
            }
        });

        jLabel1.setText("Network Source");

        sourceTCP.setText("TCP");
        sourceTCP.setEnabled(false);
        sourceTCP.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                sourceTCPActionPerformed(evt);
            }
        });

        sourceUDP.setSelected(true);
        sourceUDP.setText("UDP");

        jLabel2.setText("IP Adress");

        ipAdress.setText("127.0.0.1");

        jLabel3.setText("Port");

        portField.setText("54345");
        portField.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                portFieldActionPerformed(evt);
            }
        });

        jLabel7.setText("Time Settings");

        jLabel8.setText("<html><body>How long do you want to save the data from the rocket, the CSV file will only contain data<br\\> from this duration</body></html>");

        jLabel9.setText("Days");

        duractionDaysSpinner.setModel(new javax.swing.SpinnerNumberModel(0, 0, 30, 1));

        jLabel10.setText("Hours");

        duractionHoursSpinner.setModel(new javax.swing.SpinnerNumberModel(2, 0, 23, 1));

        jLabel11.setText("Minutes");

        duractionMinSpinner.setModel(new javax.swing.SpinnerNumberModel(0, 0, 59, 1));

        jLabel12.setText("Seconds");

        duractionSecsSpinner.setModel(new javax.swing.SpinnerNumberModel(0, 0, 59, 1));

        jLabel13.setText("How many datapoints to save per second");

        savesPerSecond.setModel(new javax.swing.SpinnerNumberModel(2, 1, 20, 1));

        saveConfigButton.setText("Save Config");
        saveConfigButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                saveConfigButtonActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout dataPointsPerSecondSpinnerLayout = new javax.swing.GroupLayout(dataPointsPerSecondSpinner);
        dataPointsPerSecondSpinner.setLayout(dataPointsPerSecondSpinnerLayout);
        dataPointsPerSecondSpinnerLayout.setHorizontalGroup(
            dataPointsPerSecondSpinnerLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(dataPointsPerSecondSpinnerLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(dataPointsPerSecondSpinnerLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(dataPointsPerSecondSpinnerLayout.createSequentialGroup()
                        .addGroup(dataPointsPerSecondSpinnerLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(jLabel1)
                            .addGroup(dataPointsPerSecondSpinnerLayout.createSequentialGroup()
                                .addGap(12, 12, 12)
                                .addGroup(dataPointsPerSecondSpinnerLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                                    .addComponent(sourceUDP, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                    .addComponent(sourceTCP, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))))
                        .addGap(18, 18, 18)
                        .addGroup(dataPointsPerSecondSpinnerLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addGroup(dataPointsPerSecondSpinnerLayout.createSequentialGroup()
                                .addComponent(jLabel2)
                                .addGap(107, 107, 107)
                                .addComponent(jLabel3))
                            .addGroup(dataPointsPerSecondSpinnerLayout.createSequentialGroup()
                                .addComponent(ipAdress, javax.swing.GroupLayout.PREFERRED_SIZE, 160, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                                .addComponent(portField, javax.swing.GroupLayout.PREFERRED_SIZE, 160, javax.swing.GroupLayout.PREFERRED_SIZE)))
                        .addContainerGap())
                    .addGroup(dataPointsPerSecondSpinnerLayout.createSequentialGroup()
                        .addGroup(dataPointsPerSecondSpinnerLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(jLabel7)
                            .addGroup(dataPointsPerSecondSpinnerLayout.createSequentialGroup()
                                .addGap(12, 12, 12)
                                .addGroup(dataPointsPerSecondSpinnerLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                                    .addGroup(dataPointsPerSecondSpinnerLayout.createSequentialGroup()
                                        .addGap(12, 12, 12)
                                        .addComponent(jLabel9)
                                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                        .addComponent(duractionDaysSpinner, javax.swing.GroupLayout.PREFERRED_SIZE, 50, javax.swing.GroupLayout.PREFERRED_SIZE)
                                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                        .addComponent(jLabel10)
                                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                        .addComponent(duractionHoursSpinner, javax.swing.GroupLayout.PREFERRED_SIZE, 50, javax.swing.GroupLayout.PREFERRED_SIZE)
                                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                        .addComponent(jLabel11)
                                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                        .addComponent(duractionMinSpinner, javax.swing.GroupLayout.PREFERRED_SIZE, 50, javax.swing.GroupLayout.PREFERRED_SIZE)
                                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                        .addComponent(jLabel12)
                                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                        .addComponent(duractionSecsSpinner, javax.swing.GroupLayout.PREFERRED_SIZE, 50, javax.swing.GroupLayout.PREFERRED_SIZE))
                                    .addComponent(jLabel8, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                                    .addGroup(dataPointsPerSecondSpinnerLayout.createSequentialGroup()
                                        .addComponent(jLabel13)
                                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                        .addComponent(savesPerSecond, javax.swing.GroupLayout.PREFERRED_SIZE, 50, javax.swing.GroupLayout.PREFERRED_SIZE))
                                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, dataPointsPerSecondSpinnerLayout.createSequentialGroup()
                                        .addComponent(saveConfigButton)
                                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                        .addGroup(dataPointsPerSecondSpinnerLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                                            .addComponent(testModeToggle, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                            .addComponent(testModeRun, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                            .addComponent(testModePause, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                                        .addGap(32, 32, 32)))))
                        .addGap(0, 109, Short.MAX_VALUE))))
        );
        dataPointsPerSecondSpinnerLayout.setVerticalGroup(
            dataPointsPerSecondSpinnerLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, dataPointsPerSecondSpinnerLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(dataPointsPerSecondSpinnerLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel1)
                    .addComponent(jLabel2)
                    .addComponent(jLabel3))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(dataPointsPerSecondSpinnerLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(sourceTCP)
                    .addComponent(ipAdress, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(portField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(sourceUDP)
                .addGap(18, 18, 18)
                .addComponent(jLabel7)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jLabel8, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(dataPointsPerSecondSpinnerLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel9)
                    .addComponent(duractionDaysSpinner, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel10)
                    .addComponent(duractionHoursSpinner, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel11)
                    .addComponent(duractionMinSpinner, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel12)
                    .addComponent(duractionSecsSpinner, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(dataPointsPerSecondSpinnerLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel13)
                    .addComponent(savesPerSecond, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 221, Short.MAX_VALUE)
                .addComponent(testModeToggle)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(testModeRun)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(dataPointsPerSecondSpinnerLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(testModePause)
                    .addComponent(saveConfigButton))
                .addGap(62, 62, 62))
        );

        jLabel8.getAccessibleContext().setAccessibleName("<html><body>How long do you want to save the data from the rocket, the CSV file will only contain data<br\\> from this duration:</body></html>");

        jTabbedPane1.addTab("Config", dataPointsPerSecondSpinner);
        jTabbedPane1.addTab("Main Data", mainChartPanel);
        jTabbedPane1.addTab("Enviro Data", enviroChartPanel);
        jTabbedPane1.addTab("Ground Path", groundPathPanel);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jTabbedPane1)
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jTabbedPane1)
                .addContainerGap())
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void testModeToggleActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_testModeToggleActionPerformed
        // TODO add your handling code here:
        AbstractButton abstractButton = (AbstractButton) evt.getSource();
        boolean selected = abstractButton.getModel().isSelected();
        if (selected) {
            testModePause.setEnabled(true);
            testModeRun.setEnabled(true);
        } else {
            testModePause.setEnabled(false);
            testModeRun.setEnabled(false);
        }
    }//GEN-LAST:event_testModeToggleActionPerformed

    private void testModeRunActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_testModeRunActionPerformed
        if (testModeStart) {
            IDataReadable tmr = new TestModeReader();
            dataSource = new DataReader(tmr);
        } else {
            IDataReadable udp = new NetworkUDPReader(props.getPort());
            dataSource = new DataReader(udp);
        }
    }//GEN-LAST:event_testModeRunActionPerformed

    private void testModePauseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_testModePauseActionPerformed
        if (testModepaused) {
            dataSource.pauseData();
        } else {
            dataSource.unpauseData();
        }
    }//GEN-LAST:event_testModePauseActionPerformed

    private void sourceTCPActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_sourceTCPActionPerformed
        // TODO add your handling code here:
    }//GEN-LAST:event_sourceTCPActionPerformed

    private void portFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_portFieldActionPerformed
        // TODO add your handling code here:
    }//GEN-LAST:event_portFieldActionPerformed

    private void csvSaveButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_csvSaveButtonActionPerformed
        String name = rocketNameField.getText();
        CSVWriter csvOutput = new CSVWriter(name);
        Set<String> parts = dataSet.getParts();
        for (String part : parts) {
            try {
                csvOutput.writeFile(dataSet.getDataList(part));
            } catch (NoSuchTimeableArrayListException ex) {
                Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }//GEN-LAST:event_csvSaveButtonActionPerformed

    private void rocketNameFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_rocketNameFieldActionPerformed
        
    }//GEN-LAST:event_rocketNameFieldActionPerformed

    private void saveConfigButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_saveConfigButtonActionPerformed
        saveConfig();
    }//GEN-LAST:event_saveConfigButtonActionPerformed

    private void rocketNameFieldPropertyChange(java.beans.PropertyChangeEvent evt) {//GEN-FIRST:event_rocketNameFieldPropertyChange
        String save = "telemetry" + System.getProperty("file.separator") + rocketNameField.getText()+System.getProperty("file.separator");
        File saveDir = new File(save);
        if (!saveDir.exists()) {
            saveDir.mkdirs();
        }
        mainChartPanel.setSaveFolder(save);
        enviroChartPanel.setSaveFolder(save);
        groundPathPanel.setSaveFolder(save);
    }//GEN-LAST:event_rocketNameFieldPropertyChange

    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed
        this.clear();
    }//GEN-LAST:event_jButton1ActionPerformed

    public void saveAllCharts() {
        int totalTabs = jTabbedPane1.getTabCount();
        for(int i = 0; i < totalTabs; i++)
        {
            Component c = jTabbedPane1.getComponentAt(i);
            if (c instanceof JPanel && c instanceof IChartSavable) {
                IChartSavable cSave = (IChartSavable) c;
                cSave.saveChart();
            }
        }
    }
    
    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /*
         * Set the Nimbus look and feel
         */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /*
         * If Nimbus (introduced in Java SE 6) is not available, stay with the
         * default look and feel. For details see
         * http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(Main.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(Main.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(Main.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(Main.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        elderberryNi = new Main();
        elderberryThread = new Thread(elderberryNi);
        elderberryThread.start();
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JToggleButton csvSaveButton;
    private javax.swing.JPanel dataPointsPerSecondSpinner;
    private javax.swing.JSpinner duractionDaysSpinner;
    private javax.swing.JSpinner duractionHoursSpinner;
    private javax.swing.JSpinner duractionMinSpinner;
    private javax.swing.JSpinner duractionSecsSpinner;
    private elderberryni2.panels.EnviroChartPanel enviroChartPanel;
    private elderberryni2.panels.GroundPathPanel groundPathPanel;
    private javax.swing.JTextField ipAdress;
    private javax.swing.JButton jButton1;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel10;
    private javax.swing.JLabel jLabel11;
    private javax.swing.JLabel jLabel12;
    private javax.swing.JLabel jLabel13;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JLabel jLabel5;
    private javax.swing.JLabel jLabel6;
    private javax.swing.JLabel jLabel7;
    private javax.swing.JLabel jLabel8;
    private javax.swing.JLabel jLabel9;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JTabbedPane jTabbedPane1;
    private elderberryni2.panels.MainChartPanel mainChartPanel;
    private javax.swing.JLabel metLabel;
    private javax.swing.JTextField portField;
    private javax.swing.JTextField rocketNameField;
    private javax.swing.JButton saveConfigButton;
    private javax.swing.JSpinner savesPerSecond;
    private javax.swing.JRadioButton sourceTCP;
    private javax.swing.JRadioButton sourceUDP;
    private javax.swing.JTabbedPane tabbedDataPanels;
    private javax.swing.JToggleButton testModePause;
    private javax.swing.JToggleButton testModeRun;
    private javax.swing.JCheckBox testModeToggle;
    private javax.swing.JLabel utcLabel;
    // End of variables declaration//GEN-END:variables

    private static Main elderberryNi = null;
    
    private static Thread elderberryThread = null;
    private static Thread testModeThread = null;
    
    private static boolean testModeStart = false;
    private static boolean testModepaused = false;
    
    private static DataReader dataSource;
    private static TelemetryDataSet<DataContainer, Float> dataSet = null;
    
    private ElderberryProperties props = null;
    private static HashMap<String, DataPanel> dataPanels = null;
    
    /**
     *
     */
    @Override
    public void run() {
        elderberryNi.setup();
        elderberryNi.setVisible(true);
        IDataReadable udp = new NetworkUDPReader(props.getPort());
        dataSource = new DataReader(udp);
        String data = "";
        Thread groundPathThread = new Thread(groundPathPanel);
        groundPathThread.start();
        while (true) {
            data = dataSource.getData();
            if (data != null) {
                DataContainer dataContainer = new DataContainer(data);
                String uuid = dataContainer.getUuid();
                if (dataSet == null) {
                    dataSet = new TelemetryDataSet<DataContainer, Float>();
                }
                dataSet.add(uuid, dataContainer);
                dataSet.setMaxTimeDifference(new Float(props.getTimePeriodSave()));
                dataSet.setMinTimeDifference(1f / props.getSavesPerSecond());
                mainChartPanel.newDataPoint(dataContainer);
                enviroChartPanel.newDataPoint(dataContainer);
                groundPathPanel.newDataPoint(dataContainer);
                elderberryNi.setDataPanel(dataContainer);
            }
        }
    }

    private void setDataPanel(DataContainer data) {
        if (dataPanels == null) {
            dataPanels = new HashMap<String, DataPanel>();
        }
        if (dataPanels.containsKey(data.getUuid())) {
            DataPanel dataPanel = dataPanels.get(data.getUuid());
            dataPanel.setData(data);
        } else {
            DataPanel dataPanel = new DataPanel();
            dataPanel.setData(data);
            dataPanels.put(data.getUuid(), dataPanel);
            tabbedDataPanels.add("Stage "+data.getUuid(), dataPanel);
        }
        elderberryNi.utcLabel.setText(Utils.formatTime(data.getUTC()));
        elderberryNi.metLabel.setText(Utils.formatTime(data.getTimestamp()));
    }
    
    private void setup(){
        try {
            props = new ElderberryProperties();
            if (!props.isTestEnabled()) {
                testModeToggle.setEnabled(false);
            }
            setProps();
        } catch (FileNotFoundException ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private void setProps() {
        switch (props.getNetworktype()) {
            case TCP:
                sourceTCP.setSelected(true);
                sourceUDP.setSelected(false);
                break;
            case UDP:
                sourceTCP.setSelected(false);
                sourceUDP.setSelected(true);
                break;
            default:
                break;
        }
        ipAdress.setText(props.getIpAdress());
        portField.setText(new Integer(props.getPort()).toString());
        if (props.isTestEnabled()) {
            testModeToggle.setEnabled(true);
        } else {
            testModeToggle.setEnabled(false);
        }
        savesPerSecond.setValue(props.getSavesPerSecond());
        int timePeriod = props.getTimePeriodSave();
        int seconds = timePeriod % 60;
        int minutes = (timePeriod / 60) % 60;
        int hours = (timePeriod / 3600) % 24;
        int days = (timePeriod / 3600) / 24;
        duractionSecsSpinner.setValue(seconds);
        duractionMinSpinner.setValue(minutes);
        duractionHoursSpinner.setValue(hours);
        duractionDaysSpinner.setValue(days);
    }

    private void saveConfig() {
        if (sourceTCP.isSelected()) {
            props.setNetworktype(NetworkType.TCP);
        }
        if (sourceUDP.isSelected()) {
            props.setNetworktype(NetworkType.UDP);
        }
        props.setIpAdress(ipAdress.getText());
        props.setPort(Integer.parseInt(portField.getText()));
        props.setSavesPerSecond((Integer) savesPerSecond.getValue());
        int seconds = (Integer) duractionSecsSpinner.getValue();
        int minutes = (Integer) duractionMinSpinner.getValue();
        int hours = (Integer) duractionHoursSpinner.getValue();
        int days = (Integer) duractionDaysSpinner.getValue();
        int timePeriod = seconds + minutes * 60 + hours * 3600 + days * 24 * 3600;
        props.setTimePeriodSave(timePeriod);
        props.saveProps();
        mainChartPanel.setSavesPerSecond((Integer) savesPerSecond.getValue());
        enviroChartPanel.setSavesPerSecond((Integer) savesPerSecond.getValue());
    }
    
    private void clear() {
        try {
            dataSet.clear();
            mainChartPanel.clear();
            enviroChartPanel.clear();
            groundPathPanel.clear(); 
        } catch (NullPointerException e) {}
    }

    private void setupLogging() {
    }
}
